'use strict'

//切换文件所在目录
process.chdir(__dirname)

const titbit = require('titbit')
const fs = require("fs")
const dbcfg = require("./dbconfig.js")
const pg = require("pg")
const wxkey = require('./wxkey.js')
const {httpcli} = require('gohttp')
const token = require('titbit-token')
const tbloader = require('titbit-loader')

//解决跨域
// const {cors} = require('titbit-toolkit')
// app.pre(new cors)

//如果同级没有images文件夹则创建
try {
    fs.accessSync('./images')
} catch (err){
    fs.mkdirSync('./images')
}

let psql = new pg.Pool(dbcfg)

let cert_path = '/usr/local/share'

const app = new titbit({
    //开启调试模式，若有错误会输出错误信息
    debug: true,
    globalLog: true, //开启全局日志
    cert: `${cert_path}/api.lzjlw.top.pem`,
    key: `${cert_path}/api.lzjlw.top.key`
})

let tb = new tbloader()
tb.init(app);

app.addService('psql',psql);
app.addService('imagePath', `${__dirname}/images`);

// 添加路由
// app.get('/',async c=>{
//     c.send('ok')
// })

/**********************  content路由 ************************** */
//获取内容列表
// app.get('/content', async c =>{
    // let ret = await psql.query(`select * from content`)
    //等效于 c.res.body = ret.rows
    // c.send(ret.rows) // rows是每一个数据
// })

//获取具体内容
// app.get('/content/:id', async c =>{
//     let sqltext = `SELECT * FROM content WHERE id=$1`
//     let r = await psql.query(sqltext, [c.param.id])
//     if(r.rowCount == 0){ //rowCount是指获取了多少条id,当等于0则没有获取到
//         return c.status(404).send('content not found')
//     }
//     c.send(r.rows[0])//rows是数组
// })

//创建内容
// app.post('/content', async c =>{
//     try {
//         /**
//          * text/json c.body转换成字符串类型
//          */
//         //提交的Body数据通过c.body获取
//         let data = JSON.parse(c.body)
//         let sqltext = `INSERT INTO `
//                     + ` content(id, add_time, detail, title, update_time) `
//                     + ` VALUES ($1, $2, $3, $4, $5)`
//         //生成唯一ID
//         let id = c.helper.makeId() //随机生成
//         let tm = Date.now()
//         let r = await psql.query(sqltext, [
//             id, tm, data.detail, data.title, tm //对应上面的$1-$5
//         ])
//         if(r.rowCount === 0 ){
//             return c.status(500).send('failed')
//         }
//         c.send(id)
//     } catch (err){
//         c.status(400).send('it is not json data')
//     }
// })


//删除数据
// app.delete('/content/:id', async c =>{
//     let sqltext = `DELETE FROM content WHERE id=$1`
//     let r = await psql.query(sqltext, [c.param.id])
//     if(r.rowCount == 0){ //rowCount是指获取了多少条id,当等于0则没有获取到
//         return c.status(404).send('content not found')
//     }
//     c.send(r.rows[0])//rows是数组
// })

/**********************  content路由 - END ************************** */

app.get('/upload',async c=>{
    //c.reply 是响应对象，可写的流，在HTTP/1.1中指向response,在HTTP/2中指向http2stream
    await c.helper.pipe('./upload.html', c.reply)
})

// app.post('/upload',async c=>{
//     //根据name获取文件对象
//     let f = c.getFile('image')
//     if(!f){
//         return c.status(400).send('image not found')
//     }
//     //根据传入的原始文件名生成唯一文件名，主要使用f.filename的扩展名
//     let fname = c.helper.makeName(f.filename)
//     //移动文件到指定位置
//     await c.moveFile(f, `./images/${fname}`)
//     c.send(fname)
// })


// app.get('/static/*',async c =>{ 
    // *可以是任意参数或路径
// })


//返回图片数据   当表示一个参数时，‘/image/a.jpg’
// app.get('/image/:name',async c=>{ // ‘:’ 识别动态变化参数的符号
    //c.param是一个对象，其中的key值是路由参数的名称
    // let imgname = c.param.name
    // await c.helper.pipe(`./images/${imgname}`, c.reply)
// })

//使用token
let tok = new token({
    //token有效期，45秒超时，单位是秒
    expires: 45, 
    //必须是32位
    key:'012345678901234567890123456789ab',

    //必须是16位
    iv:'0123456789qwerty'
})

app.addService('tok', tok)

app.get('/mp-login/:code',async c=>{
    let auth_url = `https://api.weixin.qq.com/sns/jscode2session?appid=${wxkey.appid}&secret=${wxkey.secret}&js_code=${c.param.code}&grant_type=authorization_code`

    let ret = await httpcli.get(auth_url)
                            .then(res=>{
                                return res.json()  //加密的必须是JS对象
                            })

    c.send(tok.make(ret)) //对tok加密处理
})


// app.get('/decrypt/:token', async c=>{
//     c.send( tok.verify(c.param.token))
// })


//中间件（middleware）
// app.pre(async (c, next) => {
//     let token = c.headers.authorization || c.query.token
//     if (!token) {
//         return c.status(403).send('deny')
//     }
//     let r = tok.verify(token)
//     if (r.ok === false) {
//         return c.status(403).send(r.errcode)
//     }
//     //c.box就是一个空对象，作用是放东西。
//     c.box.user = r.data
//     await next()
// })

//运行在1234窗口
app.run(9210)




/**
 * HTTP 消息头 content-type 指定了数据的类型（数据的格式）
 * 
 * Client                                        Server
 *  content-type描述的值                            根据content-type的值决定如何解析body数据
 *  要和提交的Body数据格式一致
 * 
 *  content-type:
 *      mulipart/form-data:boundary=xxx  ---------- 文件解析
 *      text/*                 -------------------- 文本类型
 *      application/*          -------------------- 要看具体值：application/json也是文本类型
 *      ......                 -------------------- 每种类型如何处理是双方设计好的通信方式
 * 
 * 到web框架这一层面，则如何吹是开发框架设计好的，但通常都要遵循一个规则：
 *          允许开发者做自己的处理
 * 
 * 在本框架范围内：
 *      multipart类型--c.body是object类型，文件信息解析到c.files
 *      application/x-www-form-urlencoded 传统的表单类型，c.body是object类型，用于获取提交的表单数据。
 *      text/*  c.body 是文本类型，c.body = c.rawBody.toString('utf8')。
 *      其他类型： c.body 是buffer类型，就是对c.rawBody的引用。
 */

//app.delete('/content/:id',async c=>{})
//c.param.id